home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 5
/
Aminet 5 - March 1995.iso
/
Aminet
/
util
/
libs
/
type1beta5.lha
/
type1
/
src
/
scanfont.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-08
|
42KB
|
1,628 lines
/* $XConsortium: scanfont.c,v 1.10 94/02/06 16:23:17 gildea Exp $ */
/* Copyright International Business Machines,Corp. 1991
* All Rights Reserved
*
* License to use, copy, modify, and distribute this software
* and its documentation for any purpose and without fee is
* hereby granted, provided that the above copyright notice
* appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation,
* and that the name of IBM not be used in advertising or
* publicity pertaining to distribution of the software without
* specific, written prior permission.
*
* IBM PROVIDES THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES
* OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
* LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. THE ENTIRE RISK AS TO THE QUALITY AND
* PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT
* OR MAINTAIN, BELONGS TO THE LICENSEE. SHOULD ANY PORTION OF
* THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM) ASSUMES
* THE ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION. IN
* NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/* Author: Katherine A. Hitchcock IBM Almaden Research Laboratory */
#ifndef T1GST
#include "global.h"
#endif
static int rc;
static boolean InPrivateDict;
static boolean WantFontInfo;
static boolean TwoSubrs;
static psobj inputFile;
static psobj filterFile;
static psobj *inputP;
/**********************************************************************/
/* Init_BuiltInEncoding() */
/* */
/* Initializes the StandardEncoding and ISOLatin1Encoding vector. */
/* */
/**********************************************************************/
typedef struct /* Builtin Standard Encoding */
{
int index;
char *name;
}
EncodingTable;
const static EncodingTable StdEnc[] =
{
040, "space",
041, "exclam",
042, "quotedbl",
043, "numbersign",
044, "dollar",
045, "percent",
046, "ampersand",
047, "quoteright",
050, "parenleft",
051, "parenright",
052, "asterisk",
053, "plus",
054, "comma",
055, "hyphen",
056, "period",
057, "slash",
060, "zero",
061, "one",
062, "two",
063, "three",
064, "four",
065, "five",
066, "six",
067, "seven",
070, "eight",
071, "nine",
072, "colon",
073, "semicolon",
074, "less",
075, "equal",
076, "greater",
077, "question",
0100, "at",
0101, "A",
0102, "B",
0103, "C",
0104, "D",
0105, "E",
0106, "F",
0107, "G",
0110, "H",
0111, "I",
0112, "J",
0113, "K",
0114, "L",
0115, "M",
0116, "N",
0117, "O",
0120, "P",
0121, "Q",
0122, "R",
0123, "S",
0124, "T",
0125, "U",
0126, "V",
0127, "W",
0130, "X",
0131, "Y",
0132, "Z",
0133, "bracketleft",
0134, "backslash",
0135, "bracketright",
0136, "asciicircum",
0137, "underscore",
0140, "quoteleft",
0141, "a",
0142, "b",
0143, "c",
0144, "d",
0145, "e",
0146, "f",
0147, "g",
0150, "h",
0151, "i",
0152, "j",
0153, "k",
0154, "l",
0155, "m",
0156, "n",
0157, "o",
0160, "p",
0161, "q",
0162, "r",
0163, "s",
0164, "t",
0165, "u",
0166, "v",
0167, "w",
0170, "x",
0171, "y",
0172, "z",
0173, "braceleft",
0174, "bar",
0175, "braceright",
0176, "asciitilde",
0241, "exclamdown",
0242, "cent",
0243, "sterling",
0244, "fraction",
0245, "yen",
0246, "florin",
0247, "section",
0250, "currency",
0251, "quotesingle",
0252, "quotedblleft",
0253, "guillemotleft",
0254, "guilsinglleft",
0255, "guilsinglright",
0256, "fi",
0257, "fl",
0261, "endash",
0262, "dagger",
0263, "daggerdbl",
0264, "periodcentered",
0266, "paragraph",
0267, "bullet",
0270, "quotesinglbase",
0271, "quotedblbase",
0272, "quotedblright",
0273, "guillemotright",
0274, "ellipsis",
0275, "perthousand",
0277, "questiondown",
0301, "grave",
0302, "acute",
0303, "circumflex",
0304, "tilde",
0305, "macron",
0306, "breve",
0307, "dotaccent",
0310, "dieresis",
0312, "ring",
0313, "cedilla",
0315, "hungarumlaut",
0316, "ogonek",
0317, "caron",
0320, "emdash",
0341, "AE",
0343, "ordfeminine",
0350, "Lslash",
0351, "Oslash",
0352, "OE",
0353, "ordmasculine",
0361, "ae",
0365, "dotlessi",
0370, "lslash",
0371, "oslash",
0372, "oe",
0373, "germandbls",
0, 0
};
const static EncodingTable ISO8859Enc[] =
{
32, "space",
33, "exclam",
34, "quotedbl",
35, "numbersign",
36, "dollar",
37, "percent",
38, "ampersand",
39, "quoteright",
40, "parenleft",
41, "parenright",
42, "asterisk",
43, "plus",
44, "comma",
45, "minus",
46, "period",
47, "slash",
48, "zero",
49, "one",
50, "two",
51, "three",
52, "four",
53, "five",
54, "six",
55, "seven",
56, "eight",
57, "nine",
58, "colon",
59, "semicolon",
60, "less",
61, "equal",
62, "greater",
63, "question",
64, "at",
65, "A",
66, "B",
67, "C",
68, "D",
69, "E",
70, "F",
71, "G",
72, "H",
73, "I",
74, "J",
75, "K",
76, "L",
77, "M",
78, "N",
79, "O",
80, "P",
81, "Q",
82, "R",
83, "S",
84, "T",
85, "U",
86, "V",
87, "W",
88, "X",
89, "Y",
90, "Z",
91, "bracketleft",
92, "backslash",
93, "bracketright",
94, "asciicircum",
95, "underscore",
96, "quoteleft",
97, "a",
98, "b",
99, "c",
100, "d",
101, "e",
102, "f",
103, "g",
104, "h",
105, "i",
106, "j",
107, "k",
108, "l",
109, "m",
110, "n",
111, "o",
112, "p",
113, "q",
114, "r",
115, "s",
116, "t",
117, "u",
118, "v",
119, "w",
120, "x",
121, "y",
122, "z",
123, "braceleft",
124, "bar",
125, "braceright",
126, "asciitilde",
161, "exclamdown",
162, "cent",
163, "sterling",
164, "currency",
165, "yen",
166, "brokenbar",
167, "section",
168, "dieresis",
169, "copyright",
170, "ordfeminine",
171, "guillemotleft",
172, "logicalnot",
173, "hyphen",
174, "registered",
175, "macron",
176, "degree",
177, "plusminus",
178, "twosuperior",
179, "threesuperior",
180, "acute",
181, "mu",
182, "paragraph",
183, "periodcentered",
184, "cedilla",
185, "onesuperior",
186, "ordmasculine",
187, "guillemotright",
188, "onequarter",
189, "onehalf",
190, "threequarters",
191, "questiondown",
192, "Agrave",
193, "Aacute",
194, "Acircumflex",
195, "Atilde",
196, "Adieresis",
197, "Aring",
198, "AE",
199, "Ccedilla",
200, "Egrave",
201, "Eacute",
202, "Ecircumflex",
203, "Edieresis",
204, "Igrave",
205, "Iacute",
206, "Icircumflex",
207, "Idieresis",
208, "Eth",
209, "Ntilde",
210, "Ograve",
211, "Oacute",
212, "Ocircumflex",
213, "Otilde",
214, "Odieresis",
215, "multiply",
216, "Oslash",
217, "Ugrave",
218, "Uacute",
219, "Ucircumflex",
220, "Udieresis",
221, "Yacute",
222, "Thorn",
223, "germandbls",
224, "agrave",
225, "aacute",
226, "acircumflex",
227, "atilde",
228, "adieresis",
229, "aring",
230, "ae",
231, "ccedilla",
232, "egrave",
233, "eacute",
234, "ecircumflex",
235, "edieresis",
236, "igrave",
237, "iacute",
238, "icircumflex",
239, "idieresis",
240, "eth",
241, "ntilde",
242, "ograve",
243, "oacute",
244, "ocircumflex",
245, "otilde",
246, "odieresis",
247, "divide",
248, "oslash",
249, "ugrave",
250, "uacute",
251, "ucircumflex",
252, "udieresis",
253, "yacute",
254, "thorn",
255, "ydieresis",
0, 0
};
static psobj *StdEncArrayP = NULL;
psobj *ISOLatin1EncArrayP = NULL;
static psobj *MakeEncodingArrayP(const EncodingTable *encodingTable);
static int getNextValue(int valueType);
static int getInt(void);
static int getEncoding(psobj *arrayP);
static int getArray(psobj *arrayP);
static int getName(char *nameP);
static int getNbytes(int N);
static int getLiteralName(psobj *nameObjP);
static int BuildSubrs(psfont *FontP);
static int BuildCharStrings(psfont *FontP);
static int BuildFontInfo(psfont *fontP);
static int BuildPrivate(psfont *fontP);
static int GetType1Blues(psfont *fontP);
static int FindDictValue(psdict *dictP);
static psobj *MakeEncodingArrayP(const EncodingTable *encodingTable)
{
int i;
psobj *encodingArrayP;
encodingArrayP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
if (!encodingArrayP)
return NULL;
/* initialize everything to .notdef */
for (i = 0; i < 256; i++)
objFormatName(&(encodingArrayP[i]), 7, ".notdef");
for (i = 0; encodingTable[i].name; i++)
{
objFormatName(&(encodingArrayP[encodingTable[i].index]),
strlen(encodingTable[i].name),
encodingTable[i].name);
}
return (encodingArrayP);
}
boolean Init_BuiltInEncoding(void)
{
StdEncArrayP = MakeEncodingArrayP(StdEnc);
ISOLatin1EncArrayP = MakeEncodingArrayP(ISO8859Enc);
return (StdEncArrayP && ISOLatin1EncArrayP);
}
/********************************************************************/
/***================================================================***/
static int getNextValue(int valueType)
{
scan_token(inputP);
if (tokenType != valueType)
{
return (SCAN_ERROR);
}
return (SCAN_OK);
}
/***================================================================***/
/* This routine will set the global rc if there is an error */
/***================================================================***/
static int getInt(void)
{
scan_token(inputP);
if (tokenType != TOKEN_INTEGER)
{
rc = SCAN_ERROR;
return (0);
}
else
{
return (tokenValue.integer);
}
}
/***================================================================***/
/*
* See Sec 10.3 of ``Adobe Type 1 Font Format'' v1.1,
* for parsing Encoding.
*/
static int getEncoding(psobj *arrayP)
{
scan_token(inputP);
if ((tokenType == TOKEN_NAME)
&&
(((tokenLength == 16) && (!strncmp(tokenStartP, "StandardEncoding", 16))) ||
(((tokenLength == 17) && (!strncmp(tokenStartP, "ISOLatin1Encoding", 17))))))
{
/* Adobe Standard Encoding */
if (tokenLength == 16)
arrayP->data.valueP = (char *)StdEncArrayP;
else
arrayP->data.valueP = (char *)ISOLatin1EncArrayP;
arrayP->len = 256;
return (SCAN_OK);
}
else if ((tokenType == TOKEN_LEFT_BRACE) ||
(tokenType == TOKEN_LEFT_BRACKET))
{
/* Array of literal names */
psobj *objP;
int i;
objP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
if (!(objP))
return (SCAN_OUT_OF_MEMORY);
arrayP->data.valueP = (char *)objP;
arrayP->len = 256;
for (i = 0; i < 256; i++, objP++)
{
scan_token(inputP);
if (tokenType != TOKEN_LITERAL_NAME)
return (SCAN_ERROR);
if (!(vm_alloc(tokenLength)))
return (SCAN_OUT_OF_MEMORY);
objFormatName(objP, tokenLength, tokenStartP);
}
scan_token(inputP);
if ((tokenType == TOKEN_RIGHT_BRACE) ||
(tokenType == TOKEN_RIGHT_BRACKET))
return (SCAN_OK);
}
else
{
/* Must be sequences of ``dup <index> <charactername> put" */
psobj *objP;
int i;
objP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
if (!(objP))
return (SCAN_OUT_OF_MEMORY);
arrayP->data.valueP = (char *)objP;
arrayP->len = 256;
for (i = 0; i < 256; i++)
objFormatName(objP + i, 7, ".notdef");
while (TRUE)
{
scan_token(inputP);
switch (tokenType)
{
case TOKEN_NAME:
if (tokenLength == 3)
{
if (strncmp(tokenStartP, "dup", 3) == 0)
{
/* get <index> */
scan_token(inputP);
if (tokenType != TOKEN_INTEGER ||
tokenValue.integer < 0 ||
tokenValue.integer > 255)
return (SCAN_ERROR);
i = tokenValue.integer;
/* get <characer_name> */
scan_token(inputP);
if (tokenType != TOKEN_LITERAL_NAME)
return (SCAN_ERROR);
if (!(vm_alloc(tokenLength)))
return (SCAN_OUT_OF_MEMORY);
objFormatName(objP + i, tokenLength, tokenStartP);
/* get "put" */
scan_token(inputP);
if (tokenType != TOKEN_NAME)
return (SCAN_ERROR);
}
else if (strncmp(tokenStartP, "def", 3) == 0)
return (SCAN_OK);
}
break;
case TOKEN_EOF:
case TOKEN_NONE:
case TOKEN_INVALID:
return (SCAN_ERROR);
}
}
}
return (SCAN_ERROR);
}
/***================================================================***/
static int getArray(psobj *arrayP)
{
int N; /* count the items in the array */
psobj *objP;
scan_token(inputP);
if ((tokenType != TOKEN_LEFT_BRACE) &&
(tokenType != TOKEN_LEFT_BRACKET))
{
return (SCAN_ERROR);
}
/* format the array in memory, save pointer to the beginning */
arrayP->data.valueP = tokenStartP;
/* loop, picking up next object, until right BRACE or BRACKET */
N = 0;
do
{
scan_token(inputP);
if ((tokenType == TOKEN_RIGHT_BRACE) ||
(tokenType == TOKEN_RIGHT_BRACKET))
{
/* save then number of items in the array */
arrayP->len = N;
return (SCAN_OK);
}
/* allocate the space for the object */
objP = (psobj *) vm_alloc(sizeof(psobj));
if (!(objP))
return (SCAN_OUT_OF_MEMORY);
/* array is an array of numbers, (real or integer) */
if (tokenType == TOKEN_REAL)
{
objFormatReal(objP, tokenValue.real);
}
else if (tokenType == TOKEN_INTEGER)
{
objFormatInteger(objP, tokenValue.integer);
}
else
return (SCAN_ERROR);
N++;
}
while (1 > 0);
/* NOTREACHED*/
}
/***================================================================***/
static int getName(char *nameP)
{
do
{
scan_token(inputP);
if (tokenType <= TOKEN_NONE)
{
if (tokenTooLong)
return (SCAN_OUT_OF_MEMORY);
return (SCAN_ERROR);
}
}
while ((tokenType != TOKEN_NAME) ||
(0 != strncmp(tokenStartP, nameP, strlen(nameP))));
/* found */
return (SCAN_OK);
}
/***================================================================***/
static int getNbytes(int N)
{
int I;
tokenStartP = vm_next_byte();
tokenMaxP = tokenStartP + MIN(vm_free_bytes(), MAX_STRING_LEN);
if (N > vm_free_bytes())
{
return (SCAN_OUT_OF_MEMORY);
}
I = T1Read(tokenStartP, 1, N, inputP->data.fileP);
if (I != N)
return (SCAN_FILE_EOF);
return (SCAN_OK);
}
/***================================================================***/
/* getLiteralName(nameObjP) */
/* scan for next literal. */
/* if we encounter the name 'end' then terminate and say ok. */
/* It means that the CharStrings does not have as many characters */
/* as the dictionary said it would and that is ok. */
/***================================================================***/
static int getLiteralName(psobj *nameObjP)
{
do
{
scan_token(inputP);
if (tokenType <= TOKEN_NONE)
{
if (tokenTooLong)
return (SCAN_OUT_OF_MEMORY);
return (SCAN_ERROR);
}
if (tokenType == TOKEN_NAME)
{
if (0 == strncmp(tokenStartP, "end", 3))
{
return (SCAN_END);
}
}
}
while (tokenType != TOKEN_LITERAL_NAME);
nameObjP->len = tokenLength;
/* allocate all the names in the CharStrings Structure */
if (!(vm_alloc(tokenLength)))
return (SCAN_OUT_OF_MEMORY);
nameObjP->data.valueP = tokenStartP;
/* found */
return (SCAN_OK);
}
/***================================================================***/
/*
* BuildSubrs routine
*/
/***================================================================***/
static int BuildSubrs(psfont *FontP)
{
int N; /* number of values in Subrs */
int I; /* index into Subrs */
int i; /* loop thru Subrs */
int J; /* length of Subrs entry */
psobj *arrayP;
/* next token should be a positive int */
/* note: rc is set by getInt. */
N = getInt();
if (rc)
return (rc);
if (N < 0)
return (SCAN_ERROR);
/* if we already have a Subrs, then skip the second one */
/* The second one is for hiresolution devices. */
if (FontP->Subrs.data.arrayP != NULL)
{
TwoSubrs = TRUE;
/* process all the Subrs, but do not update anything */
/* can not just skip them because of the binary data */
for (i = 0; i < N; i++)
{
/* look for dup */
rc = getName("dup");
if (rc)
return (rc);
/* get 2 integers */
I = getInt();
if (rc)
return (rc);
J = getInt();
if (rc)
return (rc);
if ((I < 0) || (J < 0))
return (SCAN_ERROR);
/* get the next token, it should be RD or -|, either is ok */
rc = getNextValue(TOKEN_NAME);
if (rc != SCAN_OK)
return (rc);
rc = getNbytes(J);
if (rc)
return (rc);
}
return (SCAN_OK);
}
arrayP = (psobj *) vm_alloc(N * sizeof(psobj));
if (!(arrayP))
return (SCAN_OUT_OF_MEMORY);
FontP->Subrs.len = N;
FontP->Subrs.data.arrayP = arrayP;
/* get N values for Subrs */
for (i = 0; i < N; i++)
{
/* look for dup */
rc = getName("dup");
if (rc)
return (rc);
/* get 2 integers */
I = getInt();
if (rc)
return (rc);
J = getInt();
if (rc)
return (rc);
if ((I < 0) || (J < 0))
return (SCAN_ERROR);
arrayP[I].len = J;
/* get the next token, it should be RD or -|, either is ok */
rc = getNextValue(TOKEN_NAME);
if (rc != SCAN_OK)
return (rc);
rc = getNbytes(J);
if (rc == SCAN_OK)
{
arrayP[I].data.valueP = tokenStartP;
if (!(vm_alloc(J)))
return (SCAN_OUT_OF_MEMORY);
}
else
return (rc);
}
return (SCAN_OK);
}
/***================================================================***/
/***================================================================***/
/*
* BuildCharStrings routine
*/
/***================================================================***/
static int BuildCharStrings(psfont *FontP)
{
int N; /* number of values in CharStrings */
int i; /* loop thru Subrs */
int J; /* length of Subrs entry */
psdict *dictP;
/* next token should be a positive int */
N = getInt();
if (rc)
{
/* check if file had TwoSubrs, hi resolution stuff is in file*/
if (TwoSubrs)
{
do
{
scan_token(inputP);
if (tokenType <= TOKEN_NONE)
{
if (tokenTooLong)
return (SCAN_OUT_OF_MEMORY);
return (SCAN_ERROR);
}
}
while (tokenType != TOKEN_INTEGER);
N = tokenValue.integer;
}
else
return (rc); /* if next token was not an Int */
}
if (N <= 0)
return (SCAN_ERROR);
/* save number of entries in the dictionary */
dictP = (psdict *) vm_alloc((N + 1) * sizeof(psdict));
if (!(dictP))
return (SCAN_OUT_OF_MEMORY);
FontP->CharStringsP = dictP;
dictP[0].key.len = N;
/* get N values for CharStrings */
for (i = 1; i <= N; i++)
{
/* look for next literal name */
rc = getLiteralName(&(dictP[i].key));
if (rc)
return (rc);
/* get 1 integer */
J = getInt();
if (rc)
return (rc); /* if next token was not an Int */
if (J < 0)
return (SCAN_ERROR);
dictP[i].value.len = J;
/* get the next token, it should be RD or -|, either is ok */
rc = getNextValue(TOKEN_NAME);
if (rc != SCAN_OK)
return (rc);
rc = getNbytes(J);
if (rc == SCAN_OK)
{
dictP[i].value.data.valueP = tokenStartP;
if (!(vm_alloc(J)))
return (SCAN_OUT_OF_MEMORY);
}
else
return (rc);
}
return (SCAN_OK);
}
/***================================================================***/
/***================================================================***/
/*
* BuildFontInfo Dictionary
*/
/***================================================================***/
static int BuildFontInfo(psfont *fontP)
{
psdict *dictP;
/* allocate the private dictionary */
dictP = (psdict *) vm_alloc(20 * sizeof(psdict));
if (!(dictP))
return (SCAN_OUT_OF_MEMORY);
fontP->fontInfoP = dictP;
fontP->fontInfoP[0].key.len = 17; /* number of actual entries */
objFormatName(&(dictP[FONTNAME].key), 8, "FontName");
objFormatName(&(dictP[FONTNAME].value), 0, NULL);
objFormatName(&(dictP[PAINTTYPE].key), 9, "PaintType");
objFormatInteger(&(dictP[PAINTTYPE].value), 0);
objFormatName(&(dictP[FONTTYPENUM].key), 8, "FontType");
objFormatInteger(&(dictP[FONTTYPENUM].value), 0);
objFormatName(&(dictP[FONTMATRIX].key), 10, "FontMatrix");
objFormatArray(&(dictP[FONTMATRIX].value), 0, NULL);
objFormatName(&(dictP[FONTBBOX].key), 8, "FontBBox");
objFormatArray(&(dictP[FONTBBOX].value), 0, NULL);
objFormatName(&(dictP[ENCODING].key), 8, "Encoding");
objFormatEncoding(&(dictP[ENCODING].value), 0, NULL);
objFormatName(&(dictP[UNIQUEID].key), 8, "UniqueID");
objFormatInteger(&(dictP[UNIQUEID].value), 0);
objFormatName(&(dictP[STROKEWIDTH].key), 11, "StrokeWidth");
objFormatReal(&(dictP[STROKEWIDTH].value), 0.0);
objFormatName(&(dictP[VERSION].key), 7, "version");
objFormatString(&(dictP[VERSION].value), 0, NULL);
objFormatName(&(dictP[NOTICE].key), 6, "Notice");
objFormatString(&(dictP[NOTICE].value), 0, NULL);
objFormatName(&(dictP[FULLNAME].key), 8, "FullName");
objFormatString(&(dictP[FULLNAME].value), 0, NULL);
objFormatName(&(dictP[FAMILYNAME].key), 10, "FamilyName");
objFormatString(&(dictP[FAMILYNAME].value), 0, NULL);
objFormatName(&(dictP[WEIGHT].key), 6, "Weight");
objFormatString(&(dictP[WEIGHT].value), 0, NULL);
objFormatName(&(dictP[ITALICANGLE].key), 11, "ItalicAngle");
objFormatReal(&(dictP[ITALICANGLE].value), 0.0);
objFormatName(&(dictP[ISFIXEDPITCH].key), 12, "isFixedPitch");
objFormatBoolean(&(dictP[ISFIXEDPITCH].value), FALSE);
objFormatName(&(dictP[UNDERLINEPOSITION].key), 17, "UnderlinePosition");
objFormatReal(&(dictP[UNDERLINEPOSITION].value), 0.0);
objFormatName(&(dictP[UNDERLINETHICKNESS].key), 18, "UnderlineThickness");
objFormatReal(&(dictP[UNDERLINETHICKNESS].value), 0.0);
return (SCAN_OK);
}
/***================================================================***/
/*
* BuildPrivate Dictionary
*/
/***================================================================***/
static int BuildPrivate(psfont *fontP)
{
psdict *Private;
/* allocate the private dictionary */
Private = (psdict *) vm_alloc(20 * sizeof(psdict));
if (!(Private))
return (SCAN_OUT_OF_MEMORY);
fontP->Private = Private;
fontP->Private[0].key.len = 16; /* number of actual entries */
objFormatName(&(Private[BLUEVALUES].key), 10, "BlueValues");
objFormatArray(&(Private[BLUEVALUES].value), 0, NULL);
objFormatName(&(Private[OTHERBLUES].key), 10, "OtherBlues");
objFormatArray(&(Private[OTHERBLUES].value), 0, NULL);
objFormatName(&(Private[FAMILYBLUES].key), 11, "FamilyBlues");
objFormatArray(&(Private[FAMILYBLUES].value), 0, NULL);
objFormatName(&(Private[FAMILYOTHERBLUES].key), 16, "FamilyOtherBlues");
objFormatArray(&(Private[FAMILYOTHERBLUES].value), 0, NULL);
objFormatName(&(Private[BLUESCALE].key), 9, "BlueScale");
objFormatReal(&(Private[BLUESCALE].value), DEFAULTBLUESCALE);
objFormatName(&(Private[BLUESHIFT].key), 9, "BlueShift");
objFormatInteger(&(Private[BLUESHIFT].value), DEFAULTBLUESHIFT);
objFormatName(&(Private[BLUEFUZZ].key), 8, "BlueFuzz");
objFormatInteger(&(Private[BLUEFUZZ].value), DEFAULTBLUEFUZZ);
objFormatName(&(Private[STDHW].key), 5, "StdHW");
objFormatArray(&(Private[STDHW].value), 0, NULL);
objFormatName(&(Private[STDVW].key), 5, "StdVW");
objFormatArray(&(Private[STDVW].value), 0, NULL);
objFormatName(&(Private[STEMSNAPH].key), 9, "StemSnapH");
objFormatArray(&(Private[STEMSNAPH].value), 0, NULL);
objFormatName(&(Private[STEMSNAPV].key), 9, "StemSnapV");
objFormatArray(&(Private[STEMSNAPV].value), 0, NULL);
objFormatName(&(Private[FORCEBOLD].key), 9, "ForceBold");
objFormatBoolean(&(Private[FORCEBOLD].value), DEFAULTFORCEBOLD);
objFormatName(&(Private[LANGUAGEGROUP].key), 13, "LanguageGroup");
objFormatInteger(&(Private[LANGUAGEGROUP].value), DEFAULTLANGUAGEGROUP);
objFormatName(&(Private[LENIV].key), 5, "LenIV");
objFormatInteger(&(Private[LENIV].value), DEFAULTLENIV);
objFormatName(&(Private[RNDSTEMUP].key), 9, "RndStemUp");
objFormatBoolean(&(Private[RNDSTEMUP].value), DEFAULTRNDSTEMUP);
objFormatName(&(Private[EXPANSIONFACTOR].key), 9, "ExpansionFactor");
objFormatReal(&(Private[EXPANSIONFACTOR].value),
DEFAULTEXPANSIONFACTOR);
return (SCAN_OK);
}
/***================================================================***/
/**********************************************************************/
/* GetType1Blues(fontP) */
/* */
/* Routine to support font-level hints. */
/* */
/* Gets all the Blues information from the Private dictionary */
/* for the font. */
/* */
/* */
/**********************************************************************/
static int GetType1Blues(psfont *fontP)
{
psdict *PrivateDictP; /* the Private dict relating to hints */
struct blues_struct *blues; /* ptr for the blues struct we will allocate */
int i;
psobj *HintEntryP;
/* get the Private dictionary pointer */
PrivateDictP = fontP->Private;
/* allocate the memory for the blues structure */
blues = (struct blues_struct *)vm_alloc(sizeof(struct blues_struct));
if (!blues)
return (SCAN_OUT_OF_MEMORY);
/* Make fontP's blues ptr point to this newly allocated structure. */
fontP->BluesP = blues;
/* fill in the BlueValues array */
HintEntryP = &(PrivateDictP[BLUEVALUES].value);
/* check to see if the entry exists and if it's an array */
if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
blues->numBlueValues = 0;
else
{
/* get the number of values in the array */
if (HintEntryP->len > NUMBLUEVALUES)
{
blues->numBlueValues = NUMBLUEVALUES;
}
else
blues->numBlueValues = HintEntryP->len;
for (i = 0; i <= blues->numBlueValues - 1; ++i)
{
if (objPIsInteger(&HintEntryP->data.arrayP[i]))
blues->BlueValues[i] =
HintEntryP->data.arrayP[i].data.integer;
else if (objPIsReal(&HintEntryP->data.arrayP[i]))
blues->BlueValues[i] =
HintEntryP->data.arrayP[i].data.real;
else
blues->BlueValues[i] = 0;
}
}
/* fill in the OtherBlues array */
HintEntryP = &(PrivateDictP[OTHERBLUES].value);
/* check to see if the entry exists and if it's an array */
if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
blues->numOtherBlues = 0;
else
{
/* get the number of values in the array */
if (HintEntryP->len > NUMOTHERBLUES)
{
blues->numOtherBlues = NUMOTHERBLUES;
}
else
blues->numOtherBlues = HintEntryP->len;
for (i = 0; i <= blues->numOtherBlues - 1; ++i)
{
if (objPIsInteger(&HintEntryP->data.arrayP[i]))
blues->OtherBlues[i] =
HintEntryP->data.arrayP[i].data.integer;
else if (objPIsReal(&HintEntryP->data.arrayP[i]))
blues->OtherBlues[i] =
HintEntryP->data.arrayP[i].data.real;
else
blues->OtherBlues[i] = 0;
}
}
/* fill in the FamilyBlues array */
HintEntryP = &(PrivateDictP[FAMILYBLUES].value);
/* check to see if the entry exists and if it's an array */
if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
blues->numFamilyBlues = 0;
else
{
/* get the number of values in the array */
if (HintEntryP->len > NUMFAMILYBLUES)
{
blues->numFamilyBlues = NUMFAMILYBLUES;
}
else
blues->numFamilyBlues = HintEntryP->len;
for (i = 0; i <= blues->numFamilyBlues - 1; ++i)
{
if (objPIsInteger(&HintEntryP->data.arrayP[i]))
blues->FamilyBlues[i] =
HintEntryP->data.arrayP[i].data.integer;
else if (objPIsReal(&HintEntryP->data.arrayP[i]))
blues->FamilyBlues[i] =
HintEntryP->data.arrayP[i].data.real;
else
blues->FamilyBlues[i] = 0;
}
}
/* fill in the FamilyOtherBlues array */
HintEntryP = &(PrivateDictP[FAMILYOTHERBLUES].value);
/* check to see if the entry exists and if it's an array */
if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
blues->numFamilyOtherBlues = 0;
else
{
/* get the number of values in the array */
if (HintEntryP->len > NUMFAMILYOTHERBLUES)
{
blues->numFamilyOtherBlues = NUMFAMILYOTHERBLUES;
}
else
blues->numFamilyOtherBlues = HintEntryP->len;
for (i = 0; i <= blues->numFamilyOtherBlues - 1; ++i)
{
if (objPIsInteger(&HintEntryP->data.arrayP[i]))
blues->FamilyOtherBlues[i] =
HintEntryP->data.arrayP[i].data.integer;
else if (objPIsReal(&HintEntryP->data.arrayP[i]))
blues->FamilyOtherBlues[i] =
HintEntryP->data.arrayP[i].data.real;
else
blues->FamilyOtherBlues[i] = 0;
}
}
/* fill in the StemSnapH array */
HintEntryP = &(PrivateDictP[STEMSNAPH].value);
/* check to see if the entry exists and if it's an array */
if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
blues->numStemSnapH = 0;
else
{
/* get the number of values in the array */
if (HintEntryP->len > NUMSTEMSNAPH)
{
blues->numStemSnapH = NUMSTEMSNAPH;
}
else
blues->numStemSnapH = HintEntryP->len;
for (i = 0; i <= blues->numStemSnapH - 1; ++i)
{
if (objPIsInteger(&HintEntryP->data.arrayP[i]))
blues->StemSnapH[i] =
HintEntryP->data.arrayP[i].data.integer;
else if (objPIsReal(&HintEntryP->data.arrayP[i]))
blues->StemSnapH[i] =
HintEntryP->data.arrayP[i].data.real;
else
blues->StemSnapH[i] = 0;
}
}
/* fill in the StemSnapV array */
HintEntryP = &(PrivateDictP[STEMSNAPV].value);
/* check to see if the entry exists and if it's an array */
if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
blues->numStemSnapV = 0;
else
{
/* get the number of values in the array */
if (HintEntryP->len > NUMSTEMSNAPV)
{
blues->numStemSnapV = NUMSTEMSNAPV;
}
else
blues->numStemSnapV = HintEntryP->len;
for (i = 0; i <= blues->numStemSnapV - 1; ++i)
{
if (objPIsInteger(&HintEntryP->data.arrayP[i]))
blues->StemSnapV[i] =
HintEntryP->data.arrayP[i].data.integer;
else if (objPIsReal(&HintEntryP->data.arrayP[i]))
blues->StemSnapV[i] =
HintEntryP->data.arrayP[i].data.real;
else
blues->StemSnapV[i] = 0;
}
}
/* fill in the StdVW array */
HintEntryP = &(PrivateDictP[STDVW].value);
/* check to see if the entry exists and if it's an array */
if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
/* a value of zero signifies no entry */
blues->StdVW = 0;
else
{
if (HintEntryP->len > NUMSTDVW)
{
}
if (objPIsInteger(&HintEntryP->data.arrayP[0]))
blues->StdVW = HintEntryP->data.arrayP[0].data.integer;
else if (objPIsReal(&HintEntryP->data.arrayP[0]))
blues->StdVW = HintEntryP->data.arrayP[0].data.real;
else
blues->StdVW = 0;
}
/* fill in the StdHW array */
HintEntryP = &(PrivateDictP[STDHW].value);
/* check to see if the entry exists and if it's an array */
if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
/* a value of zero signifies no entry */
blues->StdHW = 0;
else
{
if (HintEntryP->len > NUMSTDHW)
{
}
if (objPIsInteger(&HintEntryP->data.arrayP[0]))
blues->StdHW = HintEntryP->data.arrayP[0].data.integer;
else if (objPIsReal(&HintEntryP->data.arrayP[0]))
blues->StdHW = HintEntryP->data.arrayP[0].data.real;
else
blues->StdHW = 0;
}
/* get the ptr to the BlueScale entry */
HintEntryP = &(PrivateDictP[BLUESCALE].value);
/* put the BlueScale in the blues structure */
if (objPIsInteger(HintEntryP)) /* Must be integer! */
blues->BlueScale = HintEntryP->data.integer;
else if (objPIsReal(HintEntryP)) /* Error? */
blues->BlueScale = HintEntryP->data.real;
else
blues->BlueScale = DEFAULTBLUESCALE;
/* get the ptr to the BlueShift entry */
HintEntryP = &(PrivateDictP[BLUESHIFT].value);
if (objPIsInteger(HintEntryP)) /* Must be integer! */
blues->BlueShift = HintEntryP->data.integer;
else if (objPIsReal(HintEntryP)) /* Error? */
blues->BlueShift = HintEntryP->data.real;
else
blues->BlueShift = DEFAULTBLUESHIFT;
/* get the ptr to the BlueFuzz entry */
HintEntryP = &(PrivateDictP[BLUEFUZZ].value);
if (objPIsInteger(HintEntryP)) /* Must be integer! */
blues->BlueFuzz = HintEntryP->data.integer;
else if (objPIsReal(HintEntryP)) /* Error? */
blues->BlueFuzz = HintEntryP->data.real;
else
blues->BlueFuzz = DEFAULTBLUEFUZZ;
/* get the ptr to the ForceBold entry */
HintEntryP = &(PrivateDictP[FORCEBOLD].value);
if (objPIsBoolean(HintEntryP)) /* Must be integer! */
blues->ForceBold = HintEntryP->data.boolean;
else
blues->ForceBold = DEFAULTFORCEBOLD;
/* get the ptr to the LanguageGroup entry */
HintEntryP = &(PrivateDictP[LANGUAGEGROUP].value);
if (objPIsInteger(HintEntryP)) /* Must be integer! */
blues->LanguageGroup = HintEntryP->data.integer;
else
blues->LanguageGroup = DEFAULTLANGUAGEGROUP;
/* get the ptr to the RndStemUp entry */
HintEntryP = &(PrivateDictP[RNDSTEMUP].value);
if (objPIsBoolean(HintEntryP)) /* Must be integer! */
blues->RndStemUp = HintEntryP->data.boolean;
else
blues->RndStemUp = DEFAULTRNDSTEMUP;
/* get the ptr to the lenIV entry */
HintEntryP = &(PrivateDictP[LENIV].value);
if (objPIsInteger(HintEntryP)) /* Must be integer! */
blues->lenIV = HintEntryP->data.integer;
else
blues->lenIV = DEFAULTLENIV;
/* get the ptr to the ExpansionFactor entry */
HintEntryP = &(PrivateDictP[EXPANSIONFACTOR].value);
if (objPIsInteger(HintEntryP))
blues->ExpansionFactor = HintEntryP->data.integer;
else if (objPIsReal(HintEntryP))
blues->ExpansionFactor = HintEntryP->data.real;
else
blues->ExpansionFactor = DEFAULTEXPANSIONFACTOR;
return (SCAN_OK);
}
/**********************************************************************/
/* GetType1CharString(fontP,code) */
/* */
/* Look up code in the standard encoding vector and return */
/* the charstring associated with the character name. */
/* */
/* fontP is the psfont structure. */
/* */
/* Returns a psobj (string) */
/**********************************************************************/
psobj *GetType1CharString(psfont *fontP, unsigned char code)
{
int N; /* the 'Nth' entry in the CharStrings */
psobj *charnameP; /* points to psobj that is name of character*/
psdict *CharStringsDictP; /* dictionary with char strings */
psobj *theStringP; /* the definition for the code */
if (StdEncArrayP == NULL)
{
return (NULL);
}
/* use the code to index into the standard encoding vector */
charnameP = &(StdEncArrayP[code]);
/* test if the encoding array points to a name */
if (!(objPIsName(charnameP)))
{
return (NULL);
}
/* Now that we have the character name out of the standardencoding */
/* get the character definition out of the current font */
CharStringsDictP = fontP->CharStringsP;
/* search the chars string for this charname as key */
N = SearchDictName(CharStringsDictP, charnameP);
if (N <= 0)
{
return (NULL);
}
/* OK, the nth item is the psobj that is the string for this char */
theStringP = &(CharStringsDictP[N].value);
return (theStringP);
}
/***================================================================***/
/*
* FindDictValue
*/
/***================================================================***/
static int FindDictValue(psdict *dictP)
{
psobj LitName;
int N;
int V;
/* we have just scanned a token and it is a literal name */
/* need to check if that name is in Private dictionary */
objFormatName(&LitName, tokenLength, tokenStartP);
/* is it in the dictP */
N = SearchDictName(dictP, &LitName);
/* if found */
if (N > 0)
{
/* what type */
switch (dictP[N].value.type)
{
case OBJ_ENCODING:
V = getEncoding(&(dictP[N].value));
if (V != SCAN_OK)
return (V);
break;
case OBJ_ARRAY:
V = getArray(&(dictP[N].value));
if (V != SCAN_OK)
return (V);
break;
case OBJ_INTEGER:
/* next value in integer */
dictP[N].value.data.integer = getInt();
if (rc)
return (rc); /* if next token was not an Int */
break;
case OBJ_REAL:
/* next value must be real or int, store as a real */
scan_token(inputP);
if (tokenType == TOKEN_REAL)
{
dictP[N].value.data.real = tokenValue.real;
}
else if (tokenType == TOKEN_INTEGER)
{
dictP[N].value.data.real = tokenValue.integer;
}
else
return (SCAN_ERROR);
break;
case OBJ_NAME:
V = getNextValue(TOKEN_LITERAL_NAME);
if (V != SCAN_OK)
return (V);
if (!(vm_alloc(tokenLength+1)))
return (SCAN_OUT_OF_MEMORY);
objFormatName(&(dictP[N].value), tokenLength, tokenStartP);
break;
case OBJ_STRING:
V = getNextValue(TOKEN_STRING);
if (V != SCAN_OK)
return (V);
if (!(vm_alloc(tokenLength)))
return (SCAN_OUT_OF_MEMORY);
objFormatString(&(dictP[N].value), tokenLength, tokenStartP);
break;
case OBJ_BOOLEAN:
scan_token(inputP);
if (tokenType != TOKEN_NAME)
{
return (SCAN_ERROR);
}
if (0 == strncmp(tokenStartP, "true", 4))
{
dictP[N].value.data.boolean = TRUE;
}
else if (0 == strncmp(tokenStartP, "false", 5))
{
dictP[N].value.data.boolean = FALSE;
}
else
return (SCAN_ERROR);
break;
default:
return (SCAN_ERROR);
break;
}
}
/* Name is not in dictionary. That is ok. */
return (SCAN_OK);
}
/***================================================================***/
/*
* -------------------------------------------------------------------
* Scan the next token and convert it into an object
* Result is placed on the Operand Stack as next object
* -------------------------------------------------------------------
*/
int scan_font(psfont *FontP)
{
char filename[128];
char filetype[3];
F_FILE *fileP;
const char *nameP;
int namelen;
int V;
int i;
boolean starthex80;
starthex80 = FALSE;
filetype[0] = 'r';
// filetype[1] = 'b';
// filetype[2] = '\0';
filetype[1] = '\0';
/* copy the filename and remove leading or trailing blanks */
/* point to name and search for leading blanks */
nameP = FontP->FontFileName.data.nameP;
namelen = FontP->FontFileName.len;
while (nameP[0] == ' ')
{
nameP++;
namelen--;
}
/* now remove any trailing blanks */
while ((namelen > 0) && (nameP[namelen - 1] == ' '))
{
namelen--;
}
strncpy(filename, nameP, namelen);
filename[namelen] = '\0';
/* file name is now constructed */
inputFile.data.fileP = NULL;
filterFile.data.fileP = NULL;
inputP = &inputFile;
if (fileP = T1Open(filename, filetype))
{
/* get the first byte of file */
V = T1getc(fileP);
/* if file starts with x'80' then skip next 5 bytes */
if (V == 0X80)
{
for (i = 0; i < 5; i++)
T1getc(fileP);
// V = T1getc(fileP);
starthex80 = TRUE;
}
else
T1ungetc(V, fileP);
objFormatFile(inputP, fileP);
}
else
{
return (SCAN_FILE_OPEN_ERROR);
};
WantFontInfo = TRUE;
InPrivateDict = FALSE;
TwoSubrs = FALSE;
rc = BuildFontInfo(FontP);
if (rc != 0)
return (rc);
/* Assume everything will be OK */
rc = 0;
/* Loop until complete font is read */
do
{
/* Scan the next token */
scan_token(inputP);
/* ==> tokenLength, tokenTooLong, tokenType, and tokenValue are */
/* now set */
switch (tokenType)
{
case TOKEN_EOF:
case TOKEN_NONE:
case TOKEN_INVALID:
/* in this case we are done */
if (tokenTooLong)
return (SCAN_OUT_OF_MEMORY);
rc = SCAN_ERROR;
break;
case TOKEN_LITERAL_NAME:
/* Look up the name */
tokenStartP[tokenLength] = '\0';
if (InPrivateDict)
{
if (0 == strncmp(tokenStartP, "Subrs", 5))
{
rc = BuildSubrs(FontP);
break;
}
if (0 == strncmp(tokenStartP, "CharStrings", 11))
{
rc = BuildCharStrings(FontP);
if ((rc == SCAN_OK) || (rc == SCAN_END))
{
T1Close(inputP->data.fileP);
/* Build the Blues Structure */
rc = GetType1Blues(FontP);
/* whatever the return code, return it */
/* all the work is done. This is the normal exit.*/
return (rc);
}
break;
}
// rc = FindDictValue(FontP->Private);
FindDictValue(FontP->Private);
/* we are not going to report errors */
/* Sometimes the font file may test a value such as */
/* testing to see if the font is alreadly loaded with */
/* same UniqueID. We would faile on /UniqueID get */
/* because we are expecting a int to follow UniqueID*/
/* If the correct object type does not follow a Name*/
/* then we will skip over it without reporting error*/
rc = SCAN_OK;
break;
} /* end of reading Private dictionary */
else if (0 == strncmp(tokenStartP, "Private", 7))
{
InPrivateDict = TRUE;
rc = BuildPrivate(FontP);
break;
}
else if (WantFontInfo)
{
// rc = FindDictValue(FontP->fontInfoP);
FindDictValue(FontP->fontInfoP);
/* we are not going to report errors */
rc = SCAN_OK;
break;
}
break;
case TOKEN_NAME:
if (0 == strncmp(tokenStartP, "eexec", 5))
{
/* if file started with x'80', check next 5 bytes */
if (starthex80)
{
V = T1getc(fileP);
if (V == 0X80)
{
for (i = 0; i < 5; i++)
T1getc(fileP);
// V = T1getc(fileP);
}
else
T1ungetc(V, fileP);
}
filterFile.data.fileP = inputP->data.fileP;
T1eexec(inputP->data.fileP);
if (filterFile.data.fileP == NULL)
{
T1Close(inputFile.data.fileP);
return (SCAN_FILE_OPEN_ERROR);
}
inputP = &filterFile;
WantFontInfo = FALSE;
}
break;
}
}
while (rc == 0);
T1Close(inputP->data.fileP);
if (tokenTooLong)
return (SCAN_OUT_OF_MEMORY);
return (rc);
}